/*
 * Copyright (c) 2008, Xiong Yingfei, the University of Tokyo
 * All rights reserved.
 */
package ac.jp.u_tokyo.SyncLib;

import ac.jp.u_tokyo.SyncLib.dictionaries.DictMod;
import ac.jp.u_tokyo.SyncLib.util.Helper;

public class PrimMod<T> implements Mod<T>
{
    private T _newValue;

	@Override
	public int hashCode()
	{
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((_newValue == null) ? 0 : _newValue.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj)
	{
		if (this == obj) return true;
		if (obj == null) return false;
		if (getClass() != obj.getClass()) return false;
		final PrimMod other = (PrimMod) obj;
		if (_newValue == null)
		{
			if (other._newValue != null) return false;
		}
		else if (!_newValue.equals(other._newValue)) return false;
		return true;
	}

	public PrimMod(T newValue) {
        super();
        _newValue = newValue;
    }
	
	public static final PrimMod NULL = new PrimMod(null);
	

    public T getNewValue() {
        return _newValue;
    }

	public T apply(T value)
	{
		return _newValue;
	}

	@SuppressWarnings("unchecked")
	public boolean isConflict(Mod<T> m)
	{
		if (m == null) return false;
		if (m instanceof NullMod) return false;
		if (! (m instanceof PrimMod)) return true;
		PrimMod<T> pm = (PrimMod<T>) m;
		return !Helper.areEqual(pm._newValue, _newValue);
	}

	public Mod<T> getInverse(T value)
	{
		return new PrimMod<T>(value);
	}

	public T inPlaceApply(T value)
	{
		return apply(value);
	}

	public Mod<T> merge(Mod<T> latter)
	{
		if (latter == null) return this;
		if (latter instanceof NullMod) return this;
		if (latter instanceof DictMod) return latter;
		assert latter instanceof PrimMod;
		return latter;
	}

	@Override
	public String toString()
	{
		if (_newValue == null) return "null";
		return _newValue.toString();
	}

	public Mod<T> subtract(Mod<T> subtrahend)
	{
//		assert this.merge(subtrahend).equals(this);
		if (subtrahend instanceof NullMod) return this;
		if (subtrahend.equals(this)) return NullMod.INSTANCE;
		return subtrahend;
	}



}
